package Rangel.firebrigade.cluster;

import Rangel.common.world.entity.RangelBuilding;
import Rangel.common.convex.CompositeConvexHull;
import Rangel.common.world.helper.RangelWorldHelper;
import Rangel.common.world.tools.Util;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.worldmodel.EntityID;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FireCluster extends Cluster {//火的区域划分

    private static final int CLUSTER_ENERGY_COEFFICIENT = 50;//70;
    private static final int CLUSTER_ENERGY_SECOND_COEFFICIENT = 20;
    RangelWorldHelper world;
    int idCounter;
    private List<RangelBuilding> highValueBuildings = new ArrayList<>();
    private Set<RangelBuilding> buildings;

    public FireCluster(RangelWorldHelper world) {
        super();
        this.world = world;
        this.buildings = new HashSet<>();
        idCounter = 0;
    }

    public void setControllable(double clusterEnergy) {
        double fireBrigadeEnergy = world.getWorldInfo().getEntitiesOfType(StandardEntityURN.FIRE_BRIGADE).size() * world.getScenarioInfo().getFireExtinguishMaxSum();
        boolean controllable = (clusterEnergy / CLUSTER_ENERGY_COEFFICIENT) < fireBrigadeEnergy;
        if (!isControllable() && controllable) {
            controllable = (clusterEnergy / CLUSTER_ENERGY_SECOND_COEFFICIENT) < fireBrigadeEnergy;
        }
        setControllable(controllable);
    }

    @Override
    public void updateConvexHull() {
        RangelBuilding RangelBuilding;
        convexHull = new CompositeConvexHull();
        convexObject.setConvexPolygon(convexHull.getConvexPolygon());
        if (convexObject != null && convexObject.getConvexPolygon() != null && convexObject.getConvexPolygon().npoints != 0) {
            for (int i = 0; i < convexObject.getConvexPolygon().npoints; i++) {
                convexHull.addPoint(convexObject.getConvexPolygon().xpoints[i],
                        convexObject.getConvexPolygon().ypoints[i]);
            }
        }

        for (StandardEntity entity : entities) {
            if (entity instanceof Building) {
                RangelBuilding = world.getRangelBuilding(entity.getID());
                if (isEdge && !world.getBorderBuildings().contains(RangelBuilding.getID())) {
                    setEdge(false);
                }
                for (int i = 0; i < RangelBuilding.getSelfBuilding().getApexList().length; i += 2) {
                    convexHull.addPoint(RangelBuilding.getSelfBuilding().getApexList()[i], RangelBuilding.getSelfBuilding().getApexList()[i + 1]);
                }
            }
        }
        Set<RangelBuilding> dangerBuildings = new HashSet<>();
        double clusterEnergy = 0;
        for (StandardEntity entity : getEntities()) {
            RangelBuilding burningBuilding = world.getRangelBuilding(entity.getID());
            if (burningBuilding.getEstimatedFieryness() == 1) {
                dangerBuildings.add(burningBuilding);
                clusterEnergy += burningBuilding.getEnergy();
            }
            if (burningBuilding.getEstimatedFieryness() == 2) {
                dangerBuildings.add(burningBuilding);
                clusterEnergy += burningBuilding.getEnergy();
            }
            if (burningBuilding.getEstimatedFieryness() == 3 && burningBuilding.getEstimatedTemperature() > 150) {
                dangerBuildings.add(burningBuilding);
            }
        }

        setDying(dangerBuildings.isEmpty());
        setControllable(clusterEnergy);
        buildings = dangerBuildings;
        convexObject.setConvexPolygon(convexHull.getConvexPolygon());
        setBorderEntities();
        setCentre();

    }

    private void setBorderEntities() {
        Building building;
        borderEntities.clear();

        if (convexObject.getConvexPolygon().npoints == 0)
            return;

        smallBorderPolygon = scalePolygon(convexObject.getConvexPolygon(), 0.9);
        bigBorderPolygon = scalePolygon(convexObject.getConvexPolygon(), 1.1);

        for (StandardEntity entity : entities) {

            if (entity instanceof Refuge) {
                continue;
            }
            if (!(entity instanceof Building)) {
                continue;
            }
            building = (Building) entity;
            int[] vertexes = building.getApexList();
            for (int i = 0; i < vertexes.length; i += 2) {

                if ((bigBorderPolygon.contains(vertexes[i], vertexes[i + 1])) && !(smallBorderPolygon.contains(vertexes[i], vertexes[i + 1]))) {
                    borderEntities.add(building);
                    break;
                }
            }
        }
    }

    public Set<RangelBuilding> getBuildings() {
        return buildings;
    }

    private void setCentre() {
        int sumX = 0;
        int sumY = 0;
        for (int x : convexObject.getConvexPolygon().xpoints) {
            sumX += x;
        }

        for (int y : convexObject.getConvexPolygon().ypoints) {
            sumY += y;
        }

        if (convexObject.getConvexPolygon().npoints > 0) {
            center = new Point(sumX / convexObject.getConvexPolygon().npoints, sumY / convexObject.getConvexPolygon().npoints);
        } else {
            center = new Point(0, 0);
        }

    }

    public boolean isExpandableToCenterOfMap() {
        if (isEdge()) {
            Point mapCenter = new Point(world.getMapWidth() >> 1, world.getMapHeight() >> 1);
            double distanceFireClusterToCenter = Util.distance(center, mapCenter);
            for (EntityID entityID : world.getBorderBuildings()) {
                Building building = (Building) world.getEntity(entityID);
                double distanceBuildingToCenter = Util.distance(world.getWorldInfo().getLocation(building), mapCenter);
                if (distanceBuildingToCenter <= distanceFireClusterToCenter) {
                    return true;
                }
            }
        } else {
            return true;
        }
        return false;
    }

    public List<RangelBuilding> getBuildingsInDirection() {
        return highValueBuildings;
    }
}
